﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Taurus.Components;
using System.IO;
using System.Reflection;
using Taurus.DTO;
using Taurus.Platform.XML;
using Taurus.XML;

namespace Taurus.BLL
{
    /// <summary>
    /// 替代原先的插件机制
    /// </summary>
    class ComponentsBll
    {
        #region field
        //插件目录
        private static string _basePath = AppDomain.CurrentDomain.BaseDirectory + "plugs/";
        private static List<IComponentFactory> _componentFactoryList;
        private static IPersistence<ComponentDTO> _per;

        #endregion

        #region construction

        static ComponentsBll()
        {
            _per = new ComponentPersistence();

            if (!Directory.Exists(_basePath))
            {
                Directory.CreateDirectory(_basePath);
            }
        }

        #endregion

        #region public

        public static List<IComponentFactory> AllComponents
        {
            get
            {
                List<IComponentFactory> list = new List<IComponentFactory>();
                foreach (var cf in GetAllComponents())
                {
                    bool f = true;
                    foreach (var dto in GetAllComponentDTO())
                    {
                        if (cf.GetComponent().Unique == dto.UniqueID)
                        {
                            f = false;
                            break;
                        }
                    }
                    if (!f)
                    {
                        list.Add(cf);
                    }
                }
                return list;
            }
        }

        public static List<IComponentFactory> AllUnloadComponents
        {
            get
            {
                List<IComponentFactory> list = new List<IComponentFactory>();
                foreach (var cf in GetAllComponents())
                {
                    bool f = true;
                    foreach (var dto in GetAllComponentDTO())
                    {
                        if (cf.GetComponent().Unique == dto.UniqueID)
                        {
                            f = false;
                            break;
                        }
                    }
                    if (f)
                    {
                        list.Add(cf);
                    }
                }
                return list;
            }
        }

        public static void UpdateComponentConfig(ComponentDTO dto)
        {
            _per.Update(dto);
            _per.Save();
        }
        public static void DeleteComponentConfig(ComponentDTO dto)
        {
            _per.Delete(dto);
            _per.Save();
        }
        
        #endregion

        #region private

        private static List<IComponentFactory> GetAllComponents()
        {
            if (_componentFactoryList == null)
            {
                DirectoryInfo info = new DirectoryInfo(_basePath);
                _componentFactoryList = GetComponentFactoryDirectory(info);
            }
            return _componentFactoryList;
        }

        private static List<IComponentFactory> GetComponentFactoryDirectory(DirectoryInfo info)
        {
            List<IComponentFactory> list = new List<IComponentFactory>();
            foreach (var file in info.GetFiles("*.dll"))
            {
                Assembly asm = Assembly.LoadFile(file.FullName);
                Type factoryType = typeof(IComponentFactory);
                foreach (var type in asm.GetTypes())
                {
                    if (factoryType.IsAssignableFrom(type))
                    {
                        IComponentFactory cf = ((IComponentFactory)Activator.CreateInstance(type));
                        list.Add(cf);
                    }
                }
            }
            foreach (var dir in info.GetDirectories())
            {
                list.AddRange(GetComponentFactoryDirectory(dir));
            }
            return list;
        }

        private static List<ComponentDTO> GetAllComponentDTO()
        {
            return _per.GetList(null);
        }

        #endregion
    }
}
